﻿using AutoMapper;
using HamcoWcs.Contract.ContractCommon;
using HamcoWcs.Contract.ContractForeEnd;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.MenuInfos;
using HamcoWcs.Entitys.RoleInfos;
using HamcoWcs.Entitys.RoleMenus;
using HamcoWcs.Entitys.UserInfos;
using HamcoWcs.Models.Common.Enums;
using HamcoWcs.Models.ForeEndModels.LoginInfos;
using HamcoWcs.Models.ForeEndModels.MenuInfos;
using HamcoWcs.Models.ForeEndModels.RoleInfos;
using HamcoWcs.Models.ForeEndModels.UserInfos;
using HamcoWcs.Models.NodeInfos;
using HamcoWcs.Service.Common;
using HamcoWcs.Service.Common.Encryptions.Extension;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using HamcoWcs.Models.Common;

namespace HamcoWcs.Service.ForeEnd
{
    [AutoInject(typeof(IManageService), InjectType.Scope)]
    public class ManageService : ForeEndBaseService, IManageService
    {
        public ManageService(WcsDbContext wcsDbContext, IMapper mapper, ILoggerService logger) : base(wcsDbContext, mapper, logger)
        {
        }





        #region Login
        public LoginResult Login(LoginInfo loginInfo)
        {
            var userName = loginInfo.UserName;
            var password = loginInfo.Password.ToMD5Encrypt();

            var users = _wcsDbContext.UserInfos.AsQueryable()
                                           .Where(d => d.UserNo == userName || d.UserName == userName)
                                           .ToList();

            if (users == null || users.Count == 0)
                return new LoginResult() { Code = 0, Details = "用户名不存在" };

            if (users.Count > 1)
                return new LoginResult() { Code = 0, Details = "密码错误" };



            users = users.Where(d => d.Password == password).ToList();

            var user = users.FirstOrDefault();

            if (user == null) return new LoginResult() { Code = 0, Details = "密码错误" };

            if (!user.Enabled)
                return new LoginResult() { Code = 0, Details = "该账户已禁用" };

            var result = _mapper.Map<LoginResult>(user);
            // 添加获取用户对应菜单的代码
            var menus = GetMenuByUserId(user.Id);
            var menuTree = GenerateMenuTree(menus);
            result.Menus = menuTree;
            return result;
        }

        public void Logout(string userName)
        {

        }

        #endregion

        #region Users
        public bool AddUser(UserInfoDto userInfoDto)
        {
            var user = _mapper.Map<UserInfo>(userInfoDto);
            user.Id = 0;
            user.Password = user.Password.ToMD5Encrypt();
            _wcsDbContext.Add(user);
            return Save();
        }

        public bool DeleteUser(List<DeleteUserInfo> deleteUserInfos)
        {
            var deleteIds = deleteUserInfos.Select(d => d.Id).ToList();
            var user = _wcsDbContext.UserInfos.AsQueryable().Where(d => deleteIds.Contains(d.Id)).ToList();
            _wcsDbContext.RemoveRange(user);
            return Save();
        }

        public bool UpdateUser(UserInfoDto userInfoDto)
        {
            var user = _wcsDbContext.UserInfos.AsQueryable()
                                              .AsNoTracking()
                                              .Where(d => d.Id == userInfoDto.Id)
                                              .FirstOrDefault();

            if (user != null)
            {
                if (userInfoDto.Password.IsValid())
                {
                    user.Password = userInfoDto.Password.ToMD5Encrypt();
                }

                user.Enabled = userInfoDto.Enabled;
                user.UserNo = userInfoDto.UserNo;
                user.UserName = userInfoDto.UserName;
                user.RoleId = userInfoDto.RoleId;

                _wcsDbContext.Update(user);
                return Save();
            }
            else
            {
                throw new Exception();
            }
        }
        public ForeEndResult QueryUser(QueryUserInfo query)
        {

            var usersQuery = _wcsDbContext.UserInfos.AsQueryable()
                               .WhereIf(d => d.UserNo.Contains(query.UserNo), query.UserNo)
                               .WhereIf(d => d.UserName.Contains(query.UserName), query.UserName)
                               .WhereIf(d => d.RoleId == query.RoleId, query.RoleId > 0)
                               .Pagion(query.Page, query.Size, out int count, out int pageCount)
                               .ToList();

            var usersDto = _mapper.Map<List<UserInfoDto>>(usersQuery);
            return new ForeEndResult(usersDto, count, pageCount);
        }

        public UserInfoDto GetUserByName(string userName)
        {

            var usersQuery = _wcsDbContext.UserInfos.AsQueryable()
                               .FirstOrDefault(d => d.UserName == userName);

            return  _mapper.Map<UserInfoDto>(usersQuery);
        }

        public List<MenuInfoDto> GetMenuByUserId(long UserId)
        {
                var user = _wcsDbContext.UserInfos.AsQueryable().Where(d => d.Id == UserId).FirstOrDefault();
                if (user != null)
                {
                    var role = _wcsDbContext.RoleInfos.FirstOrDefault(d => d.Id == user.RoleId);

                    if (role != null && role.Menus.Length > 0)
                    {
                        var roleDto = _mapper.Map<RoleInfoDto>(role);
                        var menus = _wcsDbContext.MenuInfos.AsQueryable()
                                                           .AsNoTracking()
                                                           .Where(d => roleDto.Menus.Contains(d.Id))
                                                           .OrderBy(d => d.MenuSort)
                                                           .ToList();

                        return _mapper.Map<List<MenuInfoDto>>(menus);
                    }
                }
                return new List<MenuInfoDto>();
        }


        #endregion

        #region Role
        public bool AddRole(RoleInfoDto roleInfoDto)
        {
            var role = _mapper.Map<RoleInfo>(roleInfoDto);
            _wcsDbContext.Add(role);
            return Save();
        }

        public bool UpdateRole(RoleInfoDto roleInfoDto)
        {
            var role = _mapper.Map<RoleInfo>(roleInfoDto);
            _wcsDbContext.Update(role);
            return Save();
        }

        public bool DeleteRole(IEnumerable<long> ids)
        {
            var roles = _wcsDbContext.RoleInfos.AsQueryable().Where(d => ids.Contains(d.Id)).ToList();
            _wcsDbContext.RemoveRange(roles);
            return Save();
        }
        public ForeEndResult QueryRole(QueryRoleInfo query)
        {
                var queryable = _wcsDbContext.RoleInfos
                                             .AsQueryable()
                                             .VagueWhereOut(query, out int count, out int pageCount)
                                             .ToList();

                var rolesDto = _mapper.Map<List<RoleInfoDto>>(queryable);
                return new ForeEndResult(rolesDto,count, pageCount);
        }


        public bool AddRoleMenu(RoleMenu roleMenu)
        {
            try
            {
                _wcsDbContext.RoleMenus.Add(roleMenu);
                return Save();
            }
            catch (Exception ex)
            {
                throw;
            }

        }

        public bool DeleteRoleMenu(RoleMenu roleMenu)
        {
            try
            {
                _wcsDbContext.RoleMenus.Remove(roleMenu);
                return Save();
            }
            catch (Exception ex)
            {
                throw;
            }

        }

        #endregion

        #region Menu
        public bool AddMenu(MenuInfoDto menuInfoDto)
        {
            var menu = _mapper.Map<MenuInfo>(menuInfoDto);
            _wcsDbContext.Add(menu);
            return Save();
        }
        public bool DeleteMenu(IEnumerable<long> ids)
        {
            var menus = _wcsDbContext.MenuInfos.AsQueryable().Where(d => ids.Contains(d.Id)).ToList();
            _wcsDbContext.RemoveRange(menus);
            return Save();
        }

        public bool UpdateMenu(MenuInfoDto menuInfoDto)
        {
            var menu = _mapper.Map<MenuInfo>(menuInfoDto);
            _wcsDbContext.Update(menu);
            return Save();
        }

        public MenuInfoResult QueryMenu()
        {
                var queryable = _wcsDbContext.MenuInfos.AsQueryable().OrderBy(d => d.MenuSort).ToList();
                var dataDtos = _mapper.Map<List<MenuInfoDto>>(queryable);
                var menuTree = GenerateMenuTree(dataDtos);
                return new MenuInfoResult(queryable.Count, 1, menuTree);
        }

        #endregion

        #region Methods

        private List<MenuInfoDto> GenerateMenuTree(List<MenuInfoDto> menuInfos)
        {
            if (menuInfos?.Count > 0)
            {
                var menuTrees = menuInfos.Where(d => d.ParentId == 0).ToList();
                foreach (var item in menuTrees)
                    GenerateMenuTree(item, menuInfos);
                return menuTrees;
            }
            else
            {
                throw new ArgumentNullException();
            }

        }

        private void GenerateMenuTree(MenuInfoDto menu, List<MenuInfoDto> menuInfos)
        {
            var menus = menuInfos.Where(d => d.ParentId == menu.Id).OrderBy(d => d.MenuSort).ToList();
            if (menus?.Count > 0)
            {
                menu.Child.AddRange(menus);
                foreach (var item in menu.Child)
                    GenerateMenuTree(item, menuInfos);
            }
        }

        #endregion
    }
}
